import { Component, NgZone, OnInit, Inject, OnDestroy } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { RestService } from '../../services/rest.service';
import { ActionTypes } from '../../models/wdl-types';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Subject } from 'rxjs/Subject';
import { takeUntil } from 'rxjs/operators';

import * as _ from 'lodash';

@Component({
  selector: 'app-user-dialog',
  templateUrl: './user-dialog.component.html',
  styleUrls: ['./user-dialog.component.css']
})
export class UserDialogComponent implements OnInit, OnDestroy {
  formGroup: FormGroup;
  caresFilterCtrl: FormControl = new FormControl();
  item: any;
  institution: any;
  title = '';
  error = '';
  cares = [];
  private _onDestroy = new Subject<void>();

  filteredCares: ReplaySubject<any[]> = new ReplaySubject<any[]>(1);

  // could be add, modify
  mode = ActionTypes.ADD;
  disabled = false;

  constructor(@Inject(MAT_DIALOG_DATA) private dialogData: any,
              public dialogRef: MatDialogRef<UserDialogComponent>,
              fb: FormBuilder,
              private ngZone: NgZone,
              private translate: TranslateService,
              private rest: RestService,
              private dialog: MatDialog) {
    this.item = dialogData.item;
    this.cares = dialogData.cares;
    this.institution = dialogData.institution;
    this.mode = dialogData.mode;

    if (this.mode === ActionTypes.ADD) {
      this.title = this.translate.get('add')['value'] + this.translate.get('user')['value'];
      this.formGroup = fb.group({
        username: [ '', [Validators.required] ],
        lastName: [ '', [] ],
        password: [ '', [Validators.required] ],
        cares: [ '', [] ],
        role: [ '', [Validators.required] ]
      });
    } else if (this.mode === ActionTypes.MODIFY) {
      this.title = this.translate.get('edit')['value'];
      this.formGroup = fb.group({
        username: [ '', [] ],
        lastName: [ '', [] ],
        cares: [ '', [] ],
        role: [ '', [Validators.required] ]
      });

      _.forEach(this.formGroup.controls, (value, key) => {
        value.value = this.item[key];
      });
    }
  }

  showCares() {
    return this.formGroup.value['role'] === 'family';
  }

  disableSubmit() {
    return this.formGroup.invalid || (this.mode === ActionTypes.MODIFY && !this.formGroup.dirty);
  }

  submit() {
    const data = {};
    _.forEach(this.formGroup.value, (value, key) => {
      if (key === 'password') {
        data[key] = value;
      } else if (key === 'cares') {
        data[key] = this.showCares() ? value : [];
      } else {
        data[key] = _.trim(value);
      }
    });

    data['firstName'] = this.institution.instName;

    // check if use exists
    const userName = _.trim(this.institution.ip) + data['username'];
    if (this.mode === ActionTypes.ADD) {
      this.error = '';
      this.rest.get('api/keycloak/validate/' + userName).subscribe(resp => {
        if (resp['status'] === 200) {
          this.error = this.translate.get('userExists')['value'];
        } else {
          data['username'] = userName;
          this.dialogRef.close(data);
        }
      }, message => {
        data['username'] = userName;
        this.dialogRef.close(data);
      });
    } else {
      data['username'] = userName;
      this.dialogRef.close(data);
    }
  }

  isAdd() {
    return this.mode === ActionTypes.ADD;
  }

  isModify() {
    return this.mode === ActionTypes.MODIFY;
  }

  private filterCares() {
    if (!this.cares) {
      return;
    }

    let search = this.caresFilterCtrl.value;
    if (!search) {
      this.filteredCares.next(this.cares.slice());
      return;
    } else {
      search = search.toLowerCase();
    }

    this.filteredCares.next(
      this.cares.filter(care => {
        return (care.personName.toLowerCase().indexOf(search) > -1) ||
               (care.rid && care.rid.toLowerCase().indexOf(search) > -1);
      })
    );
  }

  ngOnInit() {
    this.filteredCares.next(this.cares.slice());
    this.caresFilterCtrl.valueChanges
    .pipe(takeUntil(this._onDestroy))
    .subscribe(() => {
      this.filterCares();
    });

    // set initial values
    if (this.isModify()) {
      const selected = this.item['cares'];
      if (!_.isEmpty(selected)) {
        const selectedCares = [];
        selected.forEach(id => {
          selectedCares.push(_.toNumber(id));
        });
        this.formGroup.controls['cares'].setValue(selectedCares);
      }
    }
  }

  ngOnDestroy() {
    this._onDestroy.next();
    this._onDestroy.complete();
  }
}
